home *** CD-ROM | disk | FTP | other *** search
- /* RAY_RAD - A Very Simple Ray-Traced Radiosity Renderer */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
-
- #define FLOOR 0 /* X-Y plane, Z = 0.0 */
- #define SOUTH_WALL 1 /* X-Z plane, Y = 0.0 */
- #define EAST_WALL 2 /* Y-Z plane, X = 8.0 */
- #define NORTH_WALL 3 /* X-Z plane, Y = 8.0 */
- #define WEST_WALL 4 /* X-Z plane, X = 0.0 */
- #define MAX_RAYS 25000 /* Maximum number of rays */
- #define MAX_VAL 1.0e+6 /* Maximum floating point value */
- #define MIN_VAL 1.0e-6 /* Minimum floating point value */
- #define NUM_LOOP 20 /* Number of iterations */
- #define NUM_SURF 10 /* Number of surfaces */
- #define PI 3.141592654
- #define DRAND() ((double) rand() / (double) RAND_MAX)
-
- typedef struct /* 3-D point co-ordinates */
- {
- double x; /* X-axis co-ordinate */
- double y; /* Y-axis co-ordinate */
- double z; /* Z-axis co-ordinate */
- } PT_3D;
-
- typedef struct /* 3-D ray */
- {
- PT_3D org; /* Origin */
- PT_3D dir; /* Direction */
- } RAY;
-
- typedef struct /* Element */
- {
- double total; /* Total flux */
- double unsent; /* Unsent flux */
- } ELEM;
-
- typedef struct /* Surface */
- {
- PT_3D vertex[4]; /* Vertex array */
- int num_row; /* Number of element rows */
- int num_col; /* Number of element columns */
- double col_dim; /* Element column dimension */
- double row_dim; /* Element row dimension */
- double emittance; /* Emittance */
- double reflectance; /* Reflectance */
- ELEM *elemp; /* Element array pointer */
- } SURF;
-
- static int send_flux(int, int, int);
- static void display_surface(void);
- static void find_element(RAY *, int *, int *, int *);
- static void global_to_local(int, PT_3D *, PT_3D *);
- static void local_to_global(int, RAY *, RAY *);
- static void select_ray(int, int, int, RAY *);
-
- static double MaxEmittance = 0.0; /* Maximum emittance */
- static SURF RoomSurf[NUM_SURF] = { /* Room surfaces */
- { { { 0.0, 0.0, 0.0 }, { 8.0, 0.0, 0.0 }, /* Floor */
- { 8.0, 8.0, 0.0 }, { 0.0, 8.0, 0.0 } }, 8, 8, 1.0, 1.0,
- 0.0, 0.2, NULL },
- { { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 8.0 }, /* South wall */
- { 8.0, 0.0, 8.0 }, { 8.0, 0.0, 0.0 } }, 8, 8, 1.0, 1.0,
- 0.0, 0.5, NULL },
- { { { 8.0, 0.0, 0.0 }, { 8.0, 0.0, 8.0 }, /* East wall */
- { 8.0, 8.0, 8.0 }, { 8.0, 8.0, 0.0 } }, 8, 8, 1.0, 1.0,
- 0.0, 0.5, NULL },
- { { { 8.0, 8.0, 0.0 }, { 8.0, 8.0, 8.0 }, /* North wall */
- { 0.0, 8.0, 8.0 }, { 0.0, 8.0, 0.0 } }, 8, 8, 1.0, 1.0,
- 0.0, 0.5, NULL },
- { { { 0.0, 8.0, 0.0 }, { 0.0, 8.0, 8.0 }, /* West wall */
- { 0.0, 0.0, 8.0 }, { 0.0, 0.0, 0.0 } }, 8, 8, 1.0, 1.0,
- 0.0, 0.5, NULL },
- { { { 0.0, 0.0, 8.0 }, { 0.0, 3.0, 8.0 }, /* South ceil. */
- { 8.0, 3.0, 8.0 }, { 8.0, 0.0, 8.0 } }, 8, 3, 1.0, 1.0,
- 0.0, 0.8, NULL },
- { { { 5.0, 3.0, 8.0 }, { 5.0, 5.0, 8.0 }, /* East ceiling */
- { 8.0, 5.0, 8.0 }, { 8.0, 3.0, 8.0 } }, 3, 2, 1.0, 1.0,
- 0.0, 0.8, NULL },
- { { { 0.0, 5.0, 8.0 }, { 0.0, 8.0, 8.0 }, /* North ceil. */
- { 8.0, 8.0, 8.0 }, { 8.0, 5.0, 8.0 } }, 8, 3, 1.0, 1.0,
- 0.0, 0.8, NULL },
- { { { 0.0, 3.0, 8.0 }, { 0.0, 5.0, 8.0 }, /* West ceiling */
- { 3.0, 5.0, 8.0 }, { 3.0, 3.0, 8.0 } }, 3, 2, 1.0, 1.0,
- 0.0, 0.8, NULL },
- { { { 3.0, 3.0, 8.0 }, { 3.0, 5.0, 8.0 }, /* Ceil. light */
- { 5.0, 5.0, 8.0 }, { 5.0, 3.0, 8.0 } }, 2, 2, 1.0, 1.0,
- 5000.0, 0.8, NULL } };
-
- int main(void)
- {
- int col; /* Column counter */
- int elem; /* Element counter */
- int maximum; /* Maximum number of rays */
- int num_elem; /* Number of elements */
- int num_rays; /* Number of rays */
- int row; /* Row counter */
- int surf; /* Surface counter */
- ELEM *elemp; /* Element pointer */
- SURF *surfp; /* Surface pointer */
-
- for (surf = 0; surf < NUM_SURF; surf++) {
- /* Instantiate elements */
- surfp = &(RoomSurf[surf]);
- num_elem = surfp->num_row * surfp->num_col;
- if ((surfp->elemp = (ELEM *) malloc(num_elem * sizeof(ELEM)))
- == NULL) {
- fputs("Out of memory!\n", stderr);
- return (2);
- }
-
- elemp = surfp->elemp;
- for (elem = 0; elem < num_elem; elem++, elemp++)
- elemp->total = elemp->unsent = surfp->emittance;
-
- if (surfp->emittance > MaxEmittance)
- MaxEmittance = surfp->emittance;
- }
-
- do {
- /* Distribute flux between elements */
- num_rays = 0;
- for (surf = 0; surf < NUM_SURF; surf++) {
- surfp = &(RoomSurf[surf]);
- for (row = 0; row < surfp->num_row; row++)
- for (col = 0; col < surfp->num_col; col++) {
- if ((maximum = send_flux(surf, row, col)) > num_rays)
- num_rays = maximum;
- }
- }
- display_surface(); /* Display intermediate results */
- } while (num_rays > 0); /* Repeat until convergence */
-
- for (surf = 0; surf < NUM_SURF; surf++) /* Free memory */
- free(RoomSurf[surf].elemp);
-
- return (0);
- }
-
- static int send_flux ( /* Send flux to other elements */
- int s_surf, /* Sending surface index */
- int s_row, /* Sending element row */
- int s_col ) /* Sending element column */
- {
- int h_col; /* Hit element column */
- int h_row; /* Hit element row */
- int h_surf; /* Hit surface index */
- int num_rays; /* Number of rays */
- int ray; /* Ray counter */
- double inc_flux; /* Incident (ray) flux */
- double ref_flux; /* Reflected flux */
- RAY shoot; /* Shooting ray */
- ELEM *h_elemp; /* Hit element pointer */
- ELEM *s_elemp; /* Sending element pointer */
- SURF *h_surfp; /* Hit surface pointer */
- SURF *s_surfp; /* Sending surface pointer */
-
- s_surfp = &(RoomSurf[s_surf]);
- s_elemp = s_surfp->elemp + s_row * s_surfp->num_col + s_col;
-
- /* Number of rays to shoot proportional to unsent flux */
- if ((num_rays = (int) (MAX_RAYS * s_elemp->unsent /
- MaxEmittance)) == 0)
- return (0);
-
- inc_flux = s_elemp->unsent / num_rays; /* Get ray flux */
-
- for (ray = 0; ray < num_rays; ray++) { /* Distribute flux */
- select_ray(s_surf, s_row, s_col, &shoot); /* Select ray */
-
- /* Find hit surface and element */
- find_element(&shoot, &h_surf, &h_row, &h_col);
-
- /* Calculate flux reflected from hit element */
- h_surfp = &(RoomSurf[h_surf]);
- h_elemp = h_surfp->elemp + h_row * h_surfp->num_col + h_col;
- ref_flux = h_surfp->reflectance * inc_flux;
-
- h_elemp->total += ref_flux; /* Update total flux */
- h_elemp->unsent += ref_flux; /* Update unsent flux */
- }
-
- s_elemp->unsent = 0.0; /* Reset sender's unsent flux */
-
- return (num_rays);
- }
-
- static void select_ray ( /* Randomly select ray */
- int surf, /* Surface index */
- int row, /* Element row */
- int col, /* Element column */
- RAY *rayp ) /* Ray pointer */
- {
- double horz; /* Ray direction local horizontal angle */
- double vert; /* Ray direction local vertical angle */
- RAY local; /* Ray local co-ordinates */
- SURF *surfp; /* Surface pointer */
-
- surfp = &(RoomSurf[surf]);
-
- /* Randomly select local (surface) ray origin co-ordinates */
- /* within sending element boundary */
- local.org.x = ((double) col + DRAND()) / surfp->col_dim;
- local.org.y = ((double) row + DRAND()) / surfp->row_dim;
- local.org.z = 0.0;
-
- /* Randomly select local (surface) ray direction co-ordinates */
- /* with cosine probability distribution in vertical plane */
- horz = 2.0 * PI * DRAND(); /* Horizontal angle */
- vert = acos(sqrt(1.0 - DRAND())); /* Vertical angle */
-
- /* Convert from spherical to rectilinear co-ordinates */
- local.dir.x = sin(vert) * cos(horz);
- local.dir.y = sin(vert) * sin(horz);
- local.dir.z = cos(vert);
-
- /* Convert ray co-ordinates from local to global */
- local_to_global(surf, &local, rayp);
- }
-
- static void find_element ( /* Find intersected element */
- RAY *rayp, /* Ray pointer */
- int *h_surfp, /* Hit surface index pointer */
- int *h_rowp, /* Hit element row pointer */
- int *h_colp ) /* Hit element column pointer */
- {
- int surf; /* Surface counter */
- double s = MAX_VAL; /* Smallest parametric value */
- double t; /* Current parametric value */
- PT_3D hit; /* Hit point co-ordinates */
- PT_3D temp; /* Temporary point co-ordinates */
- SURF *surfp; /* Surface pointer */
-
- for (surf = 0; surf < NUM_SURF; surf++) {
- surfp = &(RoomSurf[surf]);
-
- /* Determine if and where ray intersects surface plane */
- switch (surf) {
- case EAST_WALL:
- case WEST_WALL:
- if (fabs(rayp->dir.x) > MIN_VAL) {
- t = (surfp->vertex[0].x - rayp->org.x) / rayp->dir.x;
- if (t > MIN_VAL && t < s) {
- s = t;
- *h_surfp = surf;
- }
- }
- break;
- case SOUTH_WALL:
- case NORTH_WALL:
- if (fabs(rayp->dir.y) > MIN_VAL) {
- t = (surfp->vertex[0].y - rayp->org.y) / rayp->dir.y;
- if (t > MIN_VAL && t < s) {
- s = t;
- *h_surfp = surf;
- }
- }
- break;
- case FLOOR:
- if (fabs(rayp->dir.z) > MIN_VAL) {
- t = (surfp->vertex[0].z - rayp->org.z) / rayp->dir.z;
- if (t > MIN_VAL && t < s) {
- s = t;
- *h_surfp = surf;
- }
- }
- break;
- default:
- if (fabs(rayp->dir.z) > MIN_VAL) {
- t = (surfp->vertex[0].z - rayp->org.z) / rayp->dir.z;
- if (t > MIN_VAL && t < s) {
- /* Check for intersection inside surface boundary */
- temp.x = rayp->org.x + t * rayp->dir.x;
- temp.y = rayp->org.y + t * rayp->dir.y;
- if ((temp.x >= surfp->vertex[0].x && temp.x <
- surfp->vertex[3].x) && (temp.y >=
- surfp->vertex[0].y && temp.y <
- surfp->vertex[1].y)) {
- s = t;
- *h_surfp = surf;
- }
- }
- }
- break;
- }
- }
-
- /* Calculate hit point global co-ordinates */
- temp.x = rayp->org.x + s * rayp->dir.x;
- temp.y = rayp->org.y + s * rayp->dir.y;
- temp.z = rayp->org.z + s * rayp->dir.z;
-
- /* Convert global to local (surface) co-ordinates */
- global_to_local(*h_surfp, &temp, &hit);
-
- /* Calculate hit element row and column indices */
- *h_rowp = (int) (hit.y / surfp->row_dim);
- *h_colp = (int) (hit.x / surfp->col_dim);
- }
-
- static void global_to_local ( /* Convert global to local */
- int surf, /* Surface index */
- PT_3D *globalp, /* Global co-ordinates pointer */
- PT_3D *localp ) /* Local co-ordinates pointer */
- {
- PT_3D *vp; /* Vertex pointer */
-
- vp = &(RoomSurf[surf].vertex[0]);
- switch (surf) {
- case FLOOR:
- localp->x = globalp->x - vp->x;
- localp->y = globalp->y - vp->y;
- break;
- case SOUTH_WALL:
- localp->x = globalp->z - vp->z;
- localp->y = globalp->x - vp->x;
- break;
- case EAST_WALL:
- localp->x = globalp->z - vp->z;
- localp->y = globalp->y - vp->y;
- break;
- case NORTH_WALL:
- localp->x = globalp->z - vp->z;
- localp->y = vp->x - globalp->x;
- break;
- case WEST_WALL:
- localp->x = globalp->z - vp->z;
- localp->y = vp->y - globalp->y;
- break;
- default:
- localp->x = globalp->y - vp->y;
- localp->y = globalp->x - vp->x;
- break;
- }
- }
-
- static void local_to_global ( /* Convert ray co-ordinates */
- int surf, /* Surface index */
- RAY *localp, /* Local co-ordinates pointer */
- RAY *globalp ) /* Global co-ordinates pointer */
- {
- PT_3D *vp; /* Vertex pointer */
-
- vp = &(RoomSurf[surf].vertex[0]);
- switch (surf) {
- case FLOOR:
- globalp->org.x = vp->x + localp->org.x;
- globalp->org.y = vp->y + localp->org.y;
- globalp->org.z = vp->z + localp->org.z;
- globalp->dir.x = localp->dir.x;
- globalp->dir.y = localp->dir.y;
- globalp->dir.z = localp->dir.z;
- break;
- case SOUTH_WALL:
- globalp->org.x = vp->x + localp->org.y;
- globalp->org.y = vp->y + localp->org.z;
- globalp->org.z = vp->z + localp->org.x;
- globalp->dir.x = localp->dir.y;
- globalp->dir.y = localp->dir.z;
- globalp->dir.z = localp->dir.x;
- break;
- case EAST_WALL:
- globalp->org.x = vp->x - localp->org.z;
- globalp->org.y = vp->y + localp->org.y;
- globalp->org.z = vp->z + localp->org.x;
- globalp->dir.x = -localp->dir.z;
- globalp->dir.y = localp->dir.y;
- globalp->dir.z = localp->dir.x;
- break;
- case NORTH_WALL:
- globalp->org.x = vp->x - localp->org.y;
- globalp->org.y = vp->y - localp->org.z;
- globalp->org.z = vp->z + localp->org.x;
- globalp->dir.x = -localp->dir.y;
- globalp->dir.y = -localp->dir.z;
- globalp->dir.z = localp->dir.x;
- break;
- case WEST_WALL:
- globalp->org.x = vp->x + localp->org.z;
- globalp->org.y = vp->y - localp->org.y;
- globalp->org.z = vp->z + localp->org.x;
- globalp->dir.x = localp->dir.z;
- globalp->dir.y = -localp->dir.y;
- globalp->dir.z = localp->dir.x;
- break;
- default:
- globalp->org.x = vp->x + localp->org.y;
- globalp->org.y = vp->y + localp->org.x;
- globalp->org.z = vp->z - localp->org.z;
- globalp->dir.x = localp->dir.y;
- globalp->dir.y = localp->dir.x;
- globalp->dir.z = -localp->dir.z;
- break;
- }
- }
-
- static void display_surface(void) /* Display surfaces */
- {
- int col; /* Element column index */
- int row; /* Element row index */
- int surf; /* Surface counter */
- ELEM *elemp; /* Element pointer */
- SURF *surfp; /* Surface pointer */
- static int loop = 0; /* Iteration counter */
-
- printf("Loop %d\n", loop++);
- for (surf = 0; surf < NUM_SURF; surf++) {
- printf("Surface %d\n", surf);
- surfp = &(RoomSurf[surf]);
- for (row = 0; row < surfp->num_row; row++) {
- for (col = 0; col < surfp->num_col; col++) {
- elemp = surfp->elemp + row * surfp->num_col + col;
- printf("% 8.2f ", elemp->total / (PI * surfp->row_dim *
- surfp->col_dim));
- }
- putchar('\n');
- }
- }
- }
-
-